package com.cefa.finance.service;

import com.alibaba.fastjson.JSON;
import com.cefa.finance.config.ConstantProperties;
import com.cefa.finance.dao.*;
import com.cefa.finance.model.*;
import com.cefa.finance.result.ResultModel;
import com.cefa.finance.result.ResultStatus;
import com.cefa.finance.utils.DateUtil;
import com.cefa.finance.utils.EncodingDetectUtil;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.DecimalFormat;
import java.util.*;

@Service
public class FinanceLeaseService {

    private final static Logger logger = LoggerFactory.getLogger(FinanceLeaseService.class);

    @Autowired
    private ConstantProperties constantProperties;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private VehicleRepository vehicleRepository;

    @Autowired
    private ContractRepository contractRepository;

    @Autowired
    private FileContractBlockDataRepository fileContractBlockDataRepository;

    @Autowired
    private ContractMapper contractMapper;


    @Transactional
    public ResultModel recordInfo(MultipartFile[] files, String userStr, String vehicleStr, String contractStr, Long loginUserId) {

        User userSource = JSON.parseObject(userStr, User.class);
        userSource.setRecordUser(loginUserId);
        userSource.setBlockStatus(false);

        User userUnique = userRepository.findUserByIdcode(userSource.getPhone());
        if (userUnique != null) {
            userSource.setId(userUnique.getId());
        }
        User user = userRepository.save(userSource);

        Vehicle vehicleSource = JSON.parseObject(vehicleStr, Vehicle.class);
        vehicleSource.setRecordUser(loginUserId);
        vehicleSource.setBlockStatus(false);
        Vehicle uniqueVehicle = vehicleRepository.findbyVin(vehicleSource.getVin());
        if (uniqueVehicle != null) {
            Date endDataOfLease = vehicleRepository.findEndDataOfLease(uniqueVehicle.getId());
            if (endDataOfLease != null && endDataOfLease.getTime() >= new Date().getTime()) {
                return ResultModel.ERROR(ResultStatus.NOTYETDUE);
            } else {
                vehicleSource.setId(uniqueVehicle.getId());
            }
        }
        Vehicle vehicle = vehicleRepository.save(vehicleSource);

        Contract contractSource = JSON.parseObject(contractStr, Contract.class);
        contractSource.setRecordUser(loginUserId);
        contractSource.setBlockStatus(false);
        contractSource.setVehicleId(vehicle.getId());
        contractSource.setUserId(user.getId());
        contractSource.setReportTime(new Date());
        Contract contract = contractRepository.save(contractSource);

        DecimalFormat decimalFormat = new DecimalFormat("00000000");
        String format = decimalFormat.format(contract.getId());
        String time = DateUtil.format(new Date(), "yyyyMMddHHmmss");
        contract.setReportNumber(time + format);
        contract.setReportTime(new Date());
        contractRepository.save(contract);

        Boolean isSuccess = uploadFile(files, userStr, vehicleStr, vehicle.getId(), user.getId(), contract.getId());
        if (isSuccess) {
            return ResultModel.OK(contract);
        }
        return null;
    }

    private Boolean uploadFile(MultipartFile[] files, String userStr, String vehicleStr, Long vehicleId, Long userId, Long contractId) {

        Boolean isSuccess = true;
        String filePath = constantProperties.contractPath;
        for (MultipartFile file : files) {
            if (file.isEmpty()) {
                continue;
            }
            String originalFilename = file.getOriginalFilename();
            String uploadFileName = userId + "_" + vehicleId + "_" + contractId + "_" + originalFilename;
            File dest = new File(filePath + uploadFileName);
            String absolutePath = dest.getAbsolutePath();
            if (!dest.getParentFile().exists()) {
                boolean mkdirs = dest.getParentFile().mkdirs();
            }
            try {
                file.transferTo(new File(absolutePath));
                Contract contract = contractRepository.findOne(contractId);
                String contractName = contract.getContractName() != null ? contract.getContractName().concat(",").concat(uploadFileName) : uploadFileName;
                contract.setContractName(contractName);
                contract.setOriginContractName(contract.getOriginContractName() != null ? contract.getOriginContractName().concat(",").concat(originalFilename) : originalFilename);
                contractRepository.save(contract);
            } catch (IOException e) {
                e.printStackTrace();
                logger.error(e.getMessage());
                isSuccess = false;
            }
        }
        return isSuccess;
    }


    private Boolean updateCotractFile(MultipartFile[] files, String userStr, String vehicleStr, Long vehicleId, Long userId, Long contractId) {

        Boolean isSuccess = true;
        String filePath = constantProperties.contractPath;
        for (MultipartFile file : files) {
            if (file.isEmpty()) {
                continue;
            }
            String originalFilename = file.getOriginalFilename();
            String uploadFileName = userId + "_" + vehicleId + "_" + contractId + "_" + originalFilename;
            File dest = new File(filePath + uploadFileName);
            String absolutePath = dest.getAbsolutePath();
            if (!dest.getParentFile().exists()) {
                boolean mkdirs = dest.getParentFile().mkdirs();
            }
            try {
                file.transferTo(new File(absolutePath));
            } catch (IOException e) {
                e.printStackTrace();
                logger.error(e.getMessage());
                isSuccess = false;
            }
        }
        return isSuccess;
    }


    public Map<String, Object> listLeaseInfo(String searchText, Integer pageNo, Integer pageCount) {
        ArrayList<ContractModel> allResult = new ArrayList<>();
        List<ContractModel> allContracts = contractMapper.findAllContracts();

        ArrayList<ContractModel> certainContracts = new ArrayList<>();
        HashMap<String, Object> resultMap = new HashMap<>();

        for (ContractModel contract : allContracts) {
            allResult.add(contract);
            if (searchText != null && !"".equals(searchText) && contract.getTenantryName() != null && contract.getVin() != null && contract.getPhone() != null) {
                if (contract.getTenantryName().contains(searchText) || contract.getVin().contains(searchText)
                        || contract.getPhone().contains(searchText)) {
                    certainContracts.add(contract);
                }
            }
        }

        if (searchText != null && !"".equals(searchText)) {
            allResult = certainContracts;
        }

        if (pageNo != null && pageCount != null) {
            resultMap.put("totalPage", (allResult.size() - 1) / pageCount + 1);
            allResult = new ArrayList<>(allResult.subList((pageNo - 1) * pageCount, pageCount * pageNo > allResult.size() ? allResult.size() : pageCount * pageNo));
        }
        resultMap.put("contracts", allResult);
        return resultMap;
    }


    public ResultModel downloadContract2(HttpServletRequest request, HttpServletResponse response, String fileName) {

        String filePath = constantProperties.contractPath;
        File file = new File(filePath, fileName);

        if (file.exists()) {
            ServletOutputStream outputStream = null;
            try {
                String userAgent = request.getHeader("User-Agent");
                String formFileName = file.getName();

                if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
                    formFileName = java.net.URLEncoder.encode(formFileName, "UTF-8");
                } else {
                    formFileName = new String(formFileName.getBytes("UTF-8"), "ISO-8859-1");
                }

                response.setContentType("application/force-download");
                response.setCharacterEncoding("UTF-8");
                response.setHeader("content-type", "text/html;charset=UTF-8");
                response.setHeader("Content-disposition", String.format("attachment; filename=\"%s\"", formFileName));

                String fileEncode = EncodingDetectUtil.getJavaEncode(filePath + fileName);
                String fileContent = FileUtils.readFileToString(new File(filePath, fileName), fileEncode);
                outputStream = response.getOutputStream();
                outputStream.write(fileContent.getBytes("utf-8"));
                outputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
                return ResultModel.ERROR(ResultStatus.FAILED);
            } finally {
                try {
                    if (outputStream != null) {
                        outputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return ResultModel.OK();
    }


    public ResultModel downloadContract(HttpServletRequest request, HttpServletResponse response, String fileName) throws IOException {

        String filePath = constantProperties.contractPath;
        File file = new File(filePath, fileName);
        if (file.exists()) {

            String userAgent = request.getHeader("User-Agent");
            String formFileName = file.getName();

            if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
                formFileName = java.net.URLEncoder.encode(formFileName, "UTF-8");
            } else {
                formFileName = new String(formFileName.getBytes("UTF-8"), "ISO-8859-1");
            }

            String[] split = formFileName.split("_");
            StringBuilder realName=new StringBuilder();
            for(int i=3;i<split.length;i++){
                realName.append(split[i]).append("_");
            }
            String substring = realName.substring(0, realName.length() - 1);

            response.setContentType("application/force-download");
            response.addHeader("Content-Disposition", "attachment;fileName=" + substring);
            response.setHeader("Content-type", "text/html;charset=UTF-8");

            byte[] bytes = new byte[1024];
            int len;

            BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(file));
            ServletOutputStream outputStream = response.getOutputStream();

            while ((len = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, len);
                outputStream.flush();
            }
            inputStream.close();
            outputStream.close();
        }
        return ResultModel.OK();
    }



    @Transactional("transactionManagerPrimary")
    public ResultModel updateRecordInfo(MultipartFile[] files, String userStr, String vehicleStr, String contractStr, Long contractId, Boolean updateFile, Long recordUser) {

        User userSource = JSON.parseObject(userStr, User.class);
        userSource.setBlockStatus(false);
        userSource.setRecordUser(recordUser);

        User user = userRepository.save(userSource);

        Vehicle vehicleSource = JSON.parseObject(vehicleStr, Vehicle.class);
        vehicleSource.setBlockStatus(false);
        vehicleSource.setRecordUser(recordUser);
        Vehicle vehicle = vehicleRepository.save(vehicleSource);

        Contract contractSource = JSON.parseObject(contractStr, Contract.class);
        contractSource.setBlockStatus(false);
        contractSource.setVehicleId(vehicle.getId());
        contractSource.setUserId(user.getId());
        contractSource.setRecordUser(recordUser);
        contractRepository.save(contractSource);


        if (updateFile) {
            Contract con = contractRepository.findOne(contractId);
            String contractName = "";
            if (con.getOriginContractName() != null) {
                String[] fileNames = con.getOriginContractName().split(",");
                for (String originalFilename : fileNames) {
                    String uploadFileName = user.getId() + "_" + vehicle.getId() + "_" + contractId + "_" + originalFilename;
                    contractName = contractName.concat(uploadFileName).concat(",");
                }
                contractName = contractName.substring(0, contractName.length() - 1);
            }
            con.setContractName(contractName);
            Contract save = contractRepository.save(con);

            if (files.length != 0) {
                Boolean bool = updateCotractFile(files, userStr, vehicleStr, vehicle.getId(), user.getId(), save.getId());
                if (!bool) {
                    return ResultModel.ERROR();
                }
            }
        }
        return ResultModel.OK(contractRepository.findOne(contractId));
    }

    public List<FileContractBlockData> getBlockDataInfo(Long contractId) {
        return fileContractBlockDataRepository.findByContractId(contractId);
    }
}

